home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 24 / AACD 24.iso / AACD / Sound / LAME / WarpOS / src / frontend / portableio.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-07-09  |  10.8 KB  |  479 lines

  1. /* Copyright (C) 1988-1991 Apple Computer, Inc.
  2.  * All Rights Reserved.
  3.  *
  4.  * Warranty Information
  5.  * Even though Apple has reviewed this software, Apple makes no warranty
  6.  * or representation, either express or implied, with respect to this
  7.  * software, its quality, accuracy, merchantability, or fitness for a
  8.  * particular purpose.  As a result, this software is provided "as is,"
  9.  * and you, its user, are assuming the entire risk as to its quality
  10.  * and accuracy.
  11.  *
  12.  * This code may be used and freely distributed as long as it includes
  13.  * this copyright notice and the warranty information.
  14.  *
  15.  *
  16.  * Motorola processors (Macintosh, Sun, Sparc, MIPS, etc)
  17.  * pack bytes from high to low (they are big-endian).
  18.  * Use the HighLow routines to match the native format
  19.  * of these machines.
  20.  *
  21.  * Intel-like machines (PCs, Sequent)
  22.  * pack bytes from low to high (the are little-endian).
  23.  * Use the LowHigh routines to match the native format
  24.  * of these machines.
  25.  *
  26.  * These routines have been tested on the following machines:
  27.  *    Apple Macintosh, MPW 3.1 C compiler
  28.  *    Apple Macintosh, THINK C compiler
  29.  *    Silicon Graphics IRIS, MIPS compiler
  30.  *    Cray X/MP and Y/MP
  31.  *    Digital Equipment VAX
  32.  *
  33.  *
  34.  * Implemented by Malcolm Slaney and Ken Turkowski.
  35.  *
  36.  * Malcolm Slaney contributions during 1988-1990 include big- and little-
  37.  * endian file I/O, conversion to and from Motorola's extended 80-bit
  38.  * floating-point format, and conversions to and from IEEE single-
  39.  * precision floating-point format.
  40.  *
  41.  * In 1991, Ken Turkowski implemented the conversions to and from
  42.  * IEEE double-precision format, added more precision to the extended
  43.  * conversions, and accommodated conversions involving +/- infinity,
  44.  * NaN's, and denormalized numbers.
  45.  *
  46.  * $Id: portableio.c,v 1.11 2001/01/07 23:47:38 markt Exp $
  47.  */
  48.  
  49. #ifdef HAVE_CONFIG_H
  50. # include <config.h>
  51. #endif
  52.  
  53. #include    <stdio.h>
  54. #include    <stdlib.h>
  55. #if defined(__riscos__) && defined(FPA10)
  56. #include    "ymath.h"
  57. #else
  58. #include    <math.h>
  59. #endif
  60. #include    "portableio.h"
  61.  
  62. #ifdef WITH_DMALLOC
  63. #include <dmalloc.h>
  64. #endif
  65.  
  66. /****************************************************************
  67.  * Big/little-endian independent I/O routines.
  68.  ****************************************************************/
  69.  
  70. /*
  71.  * It is a hoax to call this code portable-IO:
  72.  * 
  73.  *   - It doesn't work on machines with CHAR_BIT != 8
  74.  *   - it also don't test this error condition
  75.  *   - otherwise it tries to handle CHAR_BIT != 8 by things like 
  76.  *     masking 'putc(i&0xff,fp)'
  77.  *   - It doesn't handle EOF in any way
  78.  *   - it only works with ints with 32 or more bits
  79.  *   - It is a collection of initial buggy code with patching the known errors
  80.  *     instead of CORRECTING them! 
  81.  *     For that see comments on the old Read16BitsHighLow()
  82.  */
  83.  
  84. #ifdef KLEMM_36
  85.  
  86. signed int    ReadByte ( FILE* fp )
  87. {
  88.     int  result = getc (fp);
  89.     return result == EOF  ?  0  :  (signed char) (result & 0xFF);
  90. }
  91.  
  92. unsigned int  ReadByteUnsigned ( FILE* fp )
  93. {
  94.     int  result = getc (fp);
  95.     return result == EOF  ?  0  :  (unsigned char) (result & 0xFF);
  96. }
  97.  
  98. #else
  99.  
  100. int
  101. ReadByte(FILE *fp)
  102. {
  103.     int    result;
  104.  
  105.     result = getc(fp) & 0xff;
  106.     if (result & 0x80)
  107.         result = result - 0x100;
  108.     return result;
  109. }
  110.  
  111. #endif
  112.  
  113. #ifdef KLEMM_36
  114.  
  115. int  Read16BitsLowHigh ( FILE* fp )
  116. {
  117.     int  low  = ReadByteUnsigned (fp);
  118.     int  high = ReadByte         (fp);
  119.     
  120.     return (high << 8) | low;
  121. }
  122.  
  123. #else
  124. int
  125. Read16BitsLowHigh(FILE *fp)
  126. {
  127.     int    first, second, result;
  128.  
  129.     first = 0xff & getc(fp);
  130.     second = 0xff & getc(fp);
  131.  
  132.     result = (second << 8) + first;
  133. #ifndef    THINK_C42
  134.     if (result & 0x8000)
  135.         result = result - 0x10000;
  136. #endif    /* THINK_C */
  137.     return(result);
  138. }
  139. #endif
  140.  
  141.  
  142. #ifdef KLEMM_36
  143.  
  144. int  Read16BitsHighLow ( FILE* fp )
  145. {
  146.     int  high = ReadByte         (fp);
  147.     int  low  = ReadByteUnsigned (fp);
  148.     
  149.     return (high << 8) | low;
  150. }
  151.  
  152. #else
  153. int
  154. Read16BitsHighLow(FILE *fp)
  155. {
  156.     int    first, second, result;
  157.      
  158.         /* Reads the High bits, the value is -128...127 
  159.      * (which gave after upscaling the -32768...+32512
  160.      * Why this value is not converted to signed char?
  161.      */
  162.         first = 0xff & getc(fp);
  163.         /* Reads the Lows bits, the value is 0...255 
  164.      * This is correct. This value gives an additional offset
  165.      * for the High bits
  166.      */
  167.     second = 0xff & getc(fp);
  168.  
  169.         /* This is right */
  170.     result = (first << 8) + second;
  171.     
  172.         /* Now we are starting to correct the nasty bug of the first instruction
  173.      * The value of the high bits is wrong. Always. So we must correct this
  174.      * value. This seems to be not necessary for THINK_C42. This is either
  175.      * a 16 bit compiler with 16 bit ints (where this bug is hidden and 0x10000
  176.      * is not in the scope of an int) or it is not a C compiler, but only a
  177.      * C like compiler. In the first case the '#ifndef THINK_C42' is wrong
  178.      * because it's not a property of the THINK_C42 compiler, but of all compilers
  179.      * with sizeof(int)*CHAR_BIT < 18.
  180.      * Another nasty thing is that the rest of the code doesn't work for 16 bit ints,
  181.      * so this patch don't solve the 16 bit problem.
  182.          */
  183. #ifndef    THINK_C42
  184.     if (result & 0x8000)
  185.         result = result - 0x10000;
  186. #endif    /* THINK_C */
  187.     return(result);
  188. }
  189. #endif
  190.  
  191. void
  192. Write8Bits(FILE *fp, int i)
  193. {
  194.     putc(i&0xff,fp);
  195. }
  196.  
  197.  
  198. void
  199. Write16BitsLowHigh(FILE *fp, int i)
  200. {
  201.     putc(i&0xff,fp);
  202.     putc((i>>8)&0xff,fp);
  203. }
  204.  
  205.  
  206. void
  207. Write16BitsHighLow(FILE *fp, int i)
  208. {
  209.     putc((i>>8)&0xff,fp);
  210.     putc(i&0xff,fp);
  211. }
  212.  
  213. #ifdef KLEMM_36
  214.  
  215. int  Read24BitsHighLow ( FILE* fp )
  216. {
  217.     int  high = ReadByte         (fp);
  218.     int  med  = ReadByteUnsigned (fp);
  219.     int  low  = ReadByteUnsigned (fp);
  220.     
  221.     return (high << 16) | (med << 8) | low;
  222. }
  223.  
  224. #else
  225. int
  226. Read24BitsHighLow(FILE *fp)
  227. {
  228.     int    first, second, third;
  229.     int    result;
  230.  
  231.     first = 0xff & getc(fp);
  232.     second = 0xff & getc(fp);
  233.     third = 0xff & getc(fp);
  234.  
  235.     result = (first << 16) + (second << 8) + third;
  236.     if (result & 0x800000)
  237.         result = result - 0x1000000;
  238.     return(result);
  239. }
  240. #endif
  241.  
  242. #define    Read32BitsLowHigh(f)    Read32Bits(f)
  243.  
  244. #ifdef KLEMM_36
  245.  
  246. int  Read32Bits ( FILE* fp )
  247. {
  248.     int  low  = ReadByteUnsigned (fp);
  249.     int  medl = ReadByteUnsigned (fp);
  250.     int  medh = ReadByteUnsigned (fp);
  251.     int  high = ReadByte         (fp);
  252.  
  253.     return (high << 24) | (medh << 16) | (medl << 8) | low;
  254. }
  255.  
  256. #else
  257.  
  258. int
  259. Read32Bits(FILE *fp)
  260. {
  261.     int    first, second, result;
  262.  
  263.     first = 0xffff & Read16BitsLowHigh(fp);
  264.     second = 0xffff & Read16BitsLowHigh(fp);
  265.  
  266.     result = (second << 16) + first;
  267. #ifdef    CRAY
  268.     if (result & 0x80000000)
  269.         result = result - 0x100000000;
  270. #endif    /* CRAY */
  271.     return(result);
  272. }
  273. #endif
  274.  
  275.  
  276. #ifdef KLEMM_36
  277.  
  278. int  Read32BitsHighLow ( FILE* fp )
  279. {
  280.     int  high = ReadByte         (fp);
  281.     int  medh = ReadByteUnsigned (fp);
  282.     int  medl = ReadByteUnsigned (fp);
  283.     int  low  = ReadByteUnsigned (fp);
  284.     
  285.     return (high << 24) | (medh << 16) | (medl << 8) | low;
  286. }
  287.  
  288. #else
  289.  
  290. int
  291. Read32BitsHighLow(FILE *fp)
  292. {
  293.     int    first, second, result;
  294.  
  295.     first = 0xffff & Read16BitsHighLow(fp);
  296.     second = 0xffff & Read16BitsHighLow(fp);
  297.  
  298.     result = (first << 16) + second;
  299. #ifdef    CRAY
  300.     if (result & 0x80000000)
  301.         result = result - 0x100000000;
  302. #endif
  303.     return(result);
  304. }
  305.  
  306. #endif
  307.  
  308. void
  309. Write32Bits(FILE *fp, int i)
  310. {
  311.     Write16BitsLowHigh(fp,(int)(i&0xffffL));
  312.     Write16BitsLowHigh(fp,(int)((i>>16)&0xffffL));
  313. }
  314.  
  315.  
  316. void
  317. Write32BitsLowHigh(FILE *fp, int i)
  318. {
  319.     Write16BitsLowHigh(fp,(int)(i&0xffffL));
  320.     Write16BitsLowHigh(fp,(int)((i>>16)&0xffffL));
  321. }
  322.  
  323.  
  324. void
  325. Write32BitsHighLow(FILE *fp, int i)
  326. {
  327.     Write16BitsHighLow(fp,(int)((i>>16)&0xffffL));
  328.     Write16BitsHighLow(fp,(int)(i&0xffffL));
  329. }
  330.  
  331. #ifdef KLEMM_36
  332. void ReadBytes (FILE     *fp, char *p, int n) 
  333. {
  334.     memset ( p, 0, n );
  335.     fread  ( p, 1, n, fp );
  336. }
  337. #else
  338. void ReadBytes(FILE    *fp, char *p, int n)
  339. {
  340.     /* What about fread? */
  341.      
  342.     while (!feof(fp) & (n-- > 0))
  343.         *p++ = getc(fp);
  344. }
  345. #endif
  346.  
  347. void ReadBytesSwapped(FILE *fp, char *p, int n)
  348. {
  349.     register char    *q = p;
  350.  
  351.     /* What about fread? */
  352.       
  353.     while (!feof(fp) & (n-- > 0))
  354.         *q++ = getc(fp);
  355.  
  356.         /* If not all bytes could be read, the resorting is different
  357.      * from the normal resorting. Is this intention or another bug?
  358.      */
  359.     for (q--; p < q; p++, q--){
  360.         n = *p;
  361.         *p = *q;
  362.         *q = n;
  363.     }
  364. }
  365.  
  366. #ifdef KLEMM_36
  367. void WriteBytes(FILE *fp, char *p, int n)
  368. {
  369.     /* return n == */
  370.     fwrite ( p, 1, n, fp );
  371. }
  372. #else
  373. void WriteBytes(FILE *fp, char *p, int n)
  374. {
  375.         /* No error condition checking */
  376.         while (n-- > 0)
  377.         putc(*p++, fp);
  378. }
  379. #endif
  380. #ifdef KLEMM_36
  381. void WriteBytesSwapped(FILE *fp, char *p, int n)
  382. {
  383.     p += n;
  384.     while ( n-- > 0 )
  385.     putc ( *--p, fp );
  386. }
  387. #else
  388. void WriteBytesSwapped(FILE *fp, char *p, int n)
  389. {
  390.     p += n-1;
  391.     while (n-- > 0)
  392.         putc(*p--, fp);
  393. }
  394. #endif
  395.  
  396.  
  397.  
  398. /****************************************************************
  399.  * The following two routines make up for deficiencies in many
  400.  * compilers to convert properly between unsigned integers and
  401.  * floating-point.  Some compilers which have this bug are the
  402.  * THINK_C compiler for the Macintosh and the C compiler for the
  403.  * Silicon Graphics MIPS-based Iris.
  404.  ****************************************************************/
  405.  
  406. #ifdef applec    /* The Apple C compiler works */
  407. # define FloatToUnsigned(f)    ((unsigned long)(f))
  408. # define UnsignedToFloat(u)    ((double)(u))
  409. #else /* applec */
  410. # define FloatToUnsigned(f)    ((unsigned long)(((long)((f) - 2147483648.0)) + 2147483647L + 1))
  411. # define UnsignedToFloat(u)    (((double)((long)((u) - 2147483647L - 1))) + 2147483648.0)
  412. #endif /* applec */
  413. /****************************************************************
  414.  * Extended precision IEEE floating-point conversion routines
  415.  ****************************************************************/
  416.  
  417. double
  418. ConvertFromIeeeExtended(char* bytes)
  419. {
  420.     double    f;
  421.     long    expon;
  422.     unsigned long hiMant, loMant;
  423.  
  424. #ifdef    TEST
  425. printf("ConvertFromIEEEExtended(%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx\r",
  426.     (long)bytes[0], (long)bytes[1], (long)bytes[2], (long)bytes[3],
  427.     (long)bytes[4], (long)bytes[5], (long)bytes[6],
  428.     (long)bytes[7], (long)bytes[8], (long)bytes[9]);
  429. #endif
  430.  
  431.     expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF);
  432.     hiMant    =    ((unsigned long)(bytes[2] & 0xFF) << 24)
  433.             |    ((unsigned long)(bytes[3] & 0xFF) << 16)
  434.             |    ((unsigned long)(bytes[4] & 0xFF) << 8)
  435.             |    ((unsigned long)(bytes[5] & 0xFF));
  436.     loMant    =    ((unsigned long)(bytes[6] & 0xFF) << 24)
  437.             |    ((unsigned long)(bytes[7] & 0xFF) << 16)
  438.             |    ((unsigned long)(bytes[8] & 0xFF) << 8)
  439.             |    ((unsigned long)(bytes[9] & 0xFF));
  440.  
  441.         /* This case should also be called if the number is below the smallest
  442.      * positive double variable */
  443.     if (expon == 0 && hiMant == 0 && loMant == 0) {
  444.         f = 0;
  445.     }
  446.     else {
  447.             /* This case should also be called if the number is too large to fit into 
  448.          * a double variable */
  449.         
  450.         if (expon == 0x7FFF) {    /* Infinity or NaN */
  451.             f = HUGE_VAL;
  452.         }
  453.         else {
  454.             expon -= 16383;
  455.             f  = ldexp(UnsignedToFloat(hiMant), (int) (expon -= 31));
  456.             f += ldexp(UnsignedToFloat(loMant), (int) (expon -= 32));
  457.         }
  458.     }
  459.  
  460.     if (bytes[0] & 0x80)
  461.         return -f;
  462.     else
  463.         return f;
  464. }
  465.  
  466.  
  467.  
  468.  
  469.  
  470. double
  471. ReadIeeeExtendedHighLow(FILE *fp)
  472. {
  473.     char    bytes [10];
  474.  
  475.     ReadBytes ( fp, bytes, 10 );
  476.     return ConvertFromIeeeExtended ( bytes );
  477. }
  478.  
  479.